package ge.telasi.tasks.ui;

import ge.telasi.tasks.ejb.TaskFacadeRemote;
import ge.telasi.tasks.model.User;
import ge.telasi.tasks.ui.user.ServerItem;
import java.util.Properties;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * @author dimitri
 */
public class ServerManager {
    static public final String SERVER_ITEM = "server_item_last8995556632225";
    static public final String USERNAME = "username55522";
    static public final String PASSWORD = "password78744552";
    private User user;
    private String password;
    private ServerItem serverItem;    
    private TaskFacadeRemote facade;

    private Properties getDefaultProperties(ServerItem item) {
        String host = item.getHost();
        String port = String.valueOf(item.getPort());
        Properties props = new Properties();
        props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
        props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
        props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
        props.setProperty("org.omg.CORBA.ORBInitialHost", host);
        props.setProperty("org.omg.CORBA.ORBInitialPort", port);
        props.setProperty("java.naming.provider.url", "iiop://" + host + ":" + port);
        return props;
    }

    public void login(Platform pl, ServerItem si, String username, String password, boolean savePassword) throws Exception {
        user = getRemoteFacade(si).authorize(username, password);
        this.password = password;
        serverItem = si;
        pl.resetOnConnectionChange();
        resetQueue();
        PrefUtils.putObject(SERVER_ITEM, serverItem);
        PrefUtils.putString(USERNAME, username);
        if (savePassword) {
            PrefUtils.putString(PASSWORD, password);
        }
        else {
            PrefUtils.putString(PASSWORD, "");
        }
    }

    public boolean autoLogin() {
        ServerItem si = (ServerItem) PrefUtils.getObject(SERVER_ITEM);
        String login = PrefUtils.getString(USERNAME);
        String paswd = PrefUtils.getString(PASSWORD);
        if (si == null) return false;
        if (login == null || login.trim().length() == 0) return false;
        if (paswd == null || paswd.trim().length() == 0) return false;
        try {
            Platform pl = Platform.getDefault();
            login(pl, si, login, paswd, true);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }

    TaskFacadeRemote getRemoteFacade() throws NamingException {
        return getRemoteFacade(serverItem);
    }

    TaskFacadeRemote getRemoteFacade(ServerItem si) throws NamingException {
        InitialContext ic = new InitialContext(getDefaultProperties(si));
        facade = (TaskFacadeRemote) ic.lookup("ge.telasi.tasks.ejb.TaskFacadeRemote");
        return facade;
    }

    User getUser() {
        return user;
    }

    void setUser(User user) {
        this.user = user;
        resetQueue();
    }

    String getPassword() {
        return password;
    }

    void setPassword(String password) {
        this.password = password;
    }
    
    ServerItem getServerItem() {
        return serverItem;
    }

    void setServerItem(ServerItem serverItem) {
        this.serverItem = serverItem;
    }

    boolean isConnected() {
        return user != null && password != null && serverItem != null;
    }

    void disconnect() {
        user = null;
        password = null;
        resetQueue();
        PrefUtils.putString(PASSWORD, "");
    }

    // -- Manage messaging

    private Queue queue;
    private QueueSession queueSession;
    private QueueReceiver queueReceiver;

    private void resetQueue() {
        // close previous connection and session
        if (queueSession != null || queueReceiver != null || queue != null) {
            try {
                queueReceiver.close();
            } catch(Exception ex) {
                ex.printStackTrace();
            }
            try {
                queueSession.close();
            } catch(Exception ex) {
                ex.printStackTrace();
            }
            queueSession = null;
            queueReceiver = null;
            queue = null;
        }

        // begin new messaging service (in a new thread)
        Runnable run = new Runnable() {
            public void run() {
                startMessaging();
            }
        };
        Thread t = new Thread(run);
        t.start();
    }

    private void startMessaging() {
        if (isConnected()) {
            try {
                InitialContext ctxt = new InitialContext(getDefaultProperties(serverItem));
                QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory)
                        ctxt.lookup("queueConnectionFactory");
                queue = (Queue) ctxt.lookup("jms/TaskQueue");
                QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();
                queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                queueReceiver = queueSession.createReceiver(queue, "receiver='" + user.getUsername() + "'");
                queueReceiver.setMessageListener(new MyMessageListener());
                queueConnection.start();
            } catch(Throwable t) {
                t.printStackTrace();
            }
        }
    }

    private class MyMessageListener implements MessageListener {
        public void onMessage(Message message) {
            try {
                Platform.getDefault().refreshTaskList();
                TextMessage textMessage = (TextMessage) message;
                Platform.getDefault().addNotification(textMessage.getText());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

}
